using Tycho.Parser.Peg;

namespace Tycho.Grammar {
    public class NonTerminalCompiler : IProductionCompiler {
        private readonly INonTerminalRuleCompiler RuleCompiler;
        private readonly INonTerminalBuilder NonTerminalBuilder;

        public NonTerminalCompiler (INonTerminalRuleCompiler ruleCompiler) : this (ruleCompiler, new NonTerminalBuilder ()) {}

        public NonTerminalCompiler (INonTerminalRuleCompiler ruleCompiler, INonTerminalBuilder nonTerminalBuilder) {
            RuleCompiler = ruleCompiler;
            NonTerminalBuilder = nonTerminalBuilder;
        }

        public GrammarTree Compile (ITerm term, ChoicePrecedence precedence, ProductionCompilerContext context) {
            var production = new NonTerminal ();

            context.DeferredCompilations.AddCompilationStep (production, () => DeferredCompilationStep (term, context, precedence, production));

            return new GrammarTree (production);
        }

        private void DeferredCompilationStep (ITerm term, ProductionCompilerContext context, ChoicePrecedence precedence, NonTerminal production) {
            var productionTerm = (CompositeTerm) term;
            var name = ((IdentifierTerm) productionTerm.SubTerms["name"]).Name;
            ITerm ruleTerm = productionTerm.SubTerms["rule"];

            CompileNonTerminal (production, name, ruleTerm, precedence, context);
        }

        private void CompileNonTerminal (NonTerminal production, string name, ITerm ruleTerm, ChoicePrecedence precedence, ProductionCompilerContext context) {
            RuleCaptures ruleCaptures = RuleCompiler.Compile (ruleTerm, context);

            production.Name = name;
            NonTerminalBuilder.Build (name, production, ruleCaptures);
        }
    }
}